Introduce PHYSDEVOP_get_free_pirq
authorKeir Fraser <keir@xen.org>
Fri, 19 Nov 2010 13:45:08 +0000 (13:45 +0000)
committerKeir Fraser <keir@xen.org>
Fri, 19 Nov 2010 13:45:08 +0000 (13:45 +0000)
Introduce a new physdev_op called PHYSDEVOP_get_free_pirq to allow a
guest to get a free pirq number from Xen; the hypervisor would keep
that pirq free for the guest to use in a mapping.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/irq.c
xen/arch/x86/physdev.c
xen/arch/x86/x86_64/physdev.c
xen/include/asm-x86/irq.h
xen/include/public/physdev.h

index 3d94c8736ed30147c2b426e9f6ba755244a0188c..bb50b6113189211f8313b7e1d52d69f5300be880 100644 (file)
@@ -2448,6 +2448,7 @@ static long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         case PHYSDEVOP_unmap_pirq:
         case PHYSDEVOP_eoi:
         case PHYSDEVOP_irq_status_query:
+        case PHYSDEVOP_get_free_pirq:
             return do_physdev_op(cmd, arg);
         default:
             return -ENOSYS;
@@ -2550,6 +2551,7 @@ static long hvm_physdev_op_compat32(
         case PHYSDEVOP_unmap_pirq:
         case PHYSDEVOP_eoi:
         case PHYSDEVOP_irq_status_query:
+        case PHYSDEVOP_get_free_pirq:
             return compat_physdev_op(cmd, arg);
         break;
     default:
index ec74698c3693ad14b8c35edbaeacffc6afaf4349..6ac0cd343867c3be9f473bb68ae0ea8e8d83ceca 100644 (file)
@@ -1505,7 +1505,7 @@ int map_domain_pirq(
     old_irq = domain_pirq_to_irq(d, pirq);
     old_pirq = domain_irq_to_pirq(d, irq);
 
-    if ( (old_irq && (old_irq != irq) ) ||
+    if ( (old_irq > 0 && (old_irq != irq) ) ||
          (old_pirq && (old_pirq != pirq)) )
     {
         dprintk(XENLOG_G_WARNING, "dom%d: pirq %d or irq %d already mapped\n",
index 453b4f300697b83dc904184ac61641c0f8844736..2913a9c1b71ce52313f68718dc2a246fc0515442 100644 (file)
@@ -121,7 +121,7 @@ static int physdev_map_pirq(struct physdev_map_pirq *map)
         }
 
         irq = domain_pirq_to_irq(current->domain, map->index);
-        if ( !irq )
+        if ( irq <= 0 )
         {
             if ( IS_PRIV(current->domain) )
                 irq = map->index;
@@ -557,6 +557,26 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
                               setup_gsi.polarity);
         break; 
     }
+    case PHYSDEVOP_get_free_pirq: {
+        struct physdev_get_free_pirq out;
+        struct domain *d;
+
+        d = rcu_lock_current_domain();
+        
+        ret = -EFAULT;
+        if ( copy_from_guest(&out, arg, 1) != 0 )
+            break;
+
+        spin_lock(&d->event_lock);
+        out.pirq = get_free_pirq(d, out.type, 0);
+        d->arch.pirq_irq[out.pirq] = PIRQ_ALLOCATED;
+        spin_unlock(&d->event_lock);
+
+        ret = copy_to_guest(arg, &out, 1) ? -EFAULT : 0;
+
+        rcu_unlock_domain(d);
+        break;
+    }
     default:
         ret = -ENOSYS;
         break;
index d20eafcaff9053ee5dbf66129e1e9cf2263b416c..e3db9386b5c2857f0a11bd32d675ddfe0ef62ce4 100644 (file)
@@ -42,6 +42,9 @@
 #define physdev_manage_pci         compat_physdev_manage_pci
 #define physdev_manage_pci_t       physdev_manage_pci_compat_t
 
+#define physdev_get_free_pirq      compat_physdev_get_free_pirq
+#define physdev_get_free_pirq_t    physdev_get_free_pirq_compat_t
+
 #define COMPAT
 #undef guest_handle_okay
 #define guest_handle_okay          compat_handle_okay
index 078aa537c0e7e883509cf295c9a8da3b22709933..af6b8acc2e26988a37f3926dc78f17f27b774bf1 100644 (file)
@@ -150,6 +150,7 @@ void irq_set_affinity(struct irq_desc *, const cpumask_t *mask);
 
 #define domain_pirq_to_irq(d, pirq) ((d)->arch.pirq_irq[pirq])
 #define domain_irq_to_pirq(d, irq) ((d)->arch.irq_pirq[irq])
+#define PIRQ_ALLOCATED -1
 #define domain_pirq_to_emuirq(d, pirq) ((d)->arch.pirq_emuirq[pirq])
 #define domain_emuirq_to_pirq(d, emuirq) ((d)->arch.emuirq_pirq[emuirq])
 #define IRQ_UNBOUND -1
index 18d30593c6218e98c9fbed71ac1c21576fb89be9..82602ca6dc7506e6f9cc37e38625d33bfde7d504 100644 (file)
@@ -240,6 +240,21 @@ struct physdev_setup_gsi {
 typedef struct physdev_setup_gsi physdev_setup_gsi_t;
 DEFINE_XEN_GUEST_HANDLE(physdev_setup_gsi_t);
 
+/* leave PHYSDEVOP 22 free */
+
+/* type is MAP_PIRQ_TYPE_GSI or MAP_PIRQ_TYPE_MSI
+ * the hypercall returns a free pirq */
+#define PHYSDEVOP_get_free_pirq    23
+struct physdev_get_free_pirq {
+    /* IN */ 
+    int type;
+    /* OUT */
+    uint32_t pirq;
+};
+
+typedef struct physdev_get_free_pirq physdev_get_free_pirq_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_get_free_pirq_t);
+
 /*
  * Notify that some PIRQ-bound event channels have been unmasked.
  * ** This command is obsolete since interface version 0x00030202 and is **